import javazoom.jl.player.*;
import java.io.*;
import java.util.*;
import javax.swing.*;

public class IPSMP {

    public  MP3Player threadedPlayer;
    public  Boolean threadIsPlaying;

    public  MP3File chosenFile;
    public MP3Playlist currentPlaylist;
    public ArrayList<MP3Playlist> playlistList;
    public String  playMode; //options: "shuffle" or "continuous"

    public GUI gui;
    //public  MP3Playlist masterplaylist;
    //public static Playlist(probably a linked list) playlist


    public IPSMP() {

	threadIsPlaying = false;
	chosenFile = null; 
	playMode = "continuous";
	//this section deserialized the playlistList
	try { 	
	    FileInputStream fis = new FileInputStream("playlistList"); 
	    ObjectInputStream ois = new ObjectInputStream(fis); 
	    playlistList = (ArrayList<MP3Playlist>)ois.readObject(); 
	    ois.close(); 
	    currentPlaylist = playlistList.get(0);
	} 
	catch(Exception e) {
	    currentPlaylist = new MP3Playlist("masterplaylist");
	    playlistList = new ArrayList<MP3Playlist>(); 
	    playlistList.add(currentPlaylist);
	    //the next section of code adds the newly created masterplaylist to the playlistList and overwrites any serialized version with the new version
	    playlistList.add(currentPlaylist);
	    FileOutputStream fos = null;
	    ObjectOutputStream out = null;
	    try
		{
		    fos = new FileOutputStream("playlistList");
		    out = new ObjectOutputStream(fos);
		    out.writeObject(playlistList);
		    out.flush();
		    out.close();
		}
	    catch(IOException ex) {}
	
        //catch(NullPointerException E) {
	    // System.out.println("NullPointerExcpetion caught: User failed to select a valid file");
	    System.out.println("Could not load playlistList. A new (empty) masterplaylist has been created and added to a new (empty) playlistList.");
	}
    }


    public void importer(File chosenFile) {
	try {
	    System.out.println("importing " + chosenFile.getName());
	    MP3File newFile = new MP3File(chosenFile);

	    //the next bit of code serializes the instance of MP3File
	     FileOutputStream fos = null;
	     ObjectOutputStream out = null;
	    // try
	    // 	{
	    // 	    fos = new FileOutputStream(chosenFile.getName());
	    // 	    out = new ObjectOutputStream(fos);
	    // 	    out.writeObject(newFile);
	    // 	    out.flush();
	    // 	    out.close();
	    // 	}
	    // catch(IOException ex) {}

	    //the next section of code appends the newly added file to the masterplaylist and overwrites the serialized version with the new, appended version
	    playlistList.get(0).add(newFile);
	    try
		{
		    fos = new FileOutputStream("playlistList");
		    out = new ObjectOutputStream(fos);
		    out.writeObject(playlistList);
		    out.flush();
		    out.close();
		}
	    catch(IOException ex) {
		System.out.println("Error occured while saving playlistList  (IPSMP: line 84)");
	    }
	}
        catch(NullPointerException E) {
	    System.out.println("NullPointerExcpetion caught: User failed to select a valid file (IPSMP line 87)");
	}
    }

    public void play(MP3File selection) {
	if (selection == null) {
	    System.out.println("Doh! You tried to play a 'null' file and almost broke me, but my ingenious creator has handled this error successfully. (IPSMP: line 96)");
	    gui.showNoFileSelectedPopup();
	    return;
	}
	if (threadIsPlaying && threadedPlayer.paused) {
	    if ( (threadedPlayer.currentFile == selection) || (selection == null) ){
		threadedPlayer.player.resume();
		threadedPlayer.paused = false;
		return;
	    }
	}
	if (threadIsPlaying && !threadedPlayer.paused) {
	    if ( (threadedPlayer.currentFile == selection) || (selection == null) )
		return;
	    else {
		threadedPlayer.player.stop();
		System.out.println("stopping the song");
	    }
	}

	currentPlaylist.current  = selection;
       	System.out.println("playing " + currentPlaylist.current.toString());
	
	PlayerThread pt = new PlayerThread(currentPlaylist, this);
	threadIsPlaying = true;
	pt.start();
    }

    public void pause() {
	System.out.println("pausing");
	try {
	    threadedPlayer.player.pause();
	    threadedPlayer.paused = true;
	} 
	catch(NullPointerException E) {System.out.println("NullPointerExcpetion caught: Silly you! There's nothing to pause yet! (IPSMP: line 107)");}
    }

    public void nextTrack() {
	if (currentPlaylist.current.getNext() == null) {
	    System.out.println("I refuse to play the next track because I am already playing the last track of this playlist! It wasn't in my job description!");
	    return;
	}
	System.out.println("Playing next track");
	try {
	    threadedPlayer.player.stop();
	}
	catch(NullPointerException E) {
	    System.out.println("NullPointerException caught: cannot play next track becasue nothing is currently playing. (IPSMP: line 143)");
	    return;
	}
	if (playMode.equals("shuffle")) {
		Random r = new Random();
		int skips = r.nextInt(currentPlaylist.size);
		for (int j = 0; j < skips; j++) {
			    currentPlaylist.current = currentPlaylist.current.getNext();
			    if (currentPlaylist.current == null){
				currentPlaylist.current = currentPlaylist.head;
			    }	
		}
	}
	else 
	    currentPlaylist.current = currentPlaylist.current.getNext();
	play(currentPlaylist.current);
	  
    }

    public void prevTrack() {
	if (currentPlaylist.current.getPrev() == null) {
	    System.out.println("I refuse to play the previous track because I am already playing the first track of this playlist! It wasn't in my job description!");
	    return;
	}
	System.out.println("Playing previous track");
	try {
	    threadedPlayer.player.stop();
	}
	catch(NullPointerException E) {
	    System.out.println("NullPointerException caught: cannot play previous track becasue nothing is currently playing. (IPSMP: line 143)");
	    return;
	}
	if (playMode.equals("shuffle")) {
		Random r = new Random();
		int skips = r.nextInt(currentPlaylist.size);
		for (int j = 0; j < skips; j++) {
			    currentPlaylist.current = currentPlaylist.current.getPrev();
			    if (currentPlaylist.current == null){
				currentPlaylist.current = currentPlaylist.tail;
			    }	
	    }
	}
	else 
	    currentPlaylist.current = currentPlaylist.current.getPrev();
	play(currentPlaylist.current);
    }

    class PlayerThread extends Thread
    {
	MP3Player backgroundPlayer;
	IPSMP ipsmp;
	MP3Playlist playlist;

	public PlayerThread(MP3Playlist list, IPSMP i){
	    super();
	    ipsmp = i;
	    playlist = list;
	    backgroundPlayer = new MP3Player(playlist.current);
	    ipsmp.threadedPlayer = backgroundPlayer;
	}

	public void run()
	{
	    Random r = new Random();
	    int numPlayed = 0;
	    int total = ipsmp.currentPlaylist.size;
	    int trackNumber = 0;

	    MP3File temp = playlist.current;
	    while (temp != playlist.head) {
		temp = temp.getPrev();
		trackNumber++;
	    }

	    ArrayList<Integer> shuffle = new ArrayList<Integer>();
	    for (int i = 0; i < total; i++) {
		shuffle.add(i);
	    } 

	    while(total != numPlayed) {
		backgroundPlayer.play();
		if (backgroundPlayer.player.stopping)
		    return;
	
		if (ipsmp.playMode.equals("shuffle")) {
			trackNumber = r.nextInt(shuffle.size()); 
			for (int j = 0; j < trackNumber; j++) {
			    playlist.current = playlist.current.getNext();
			    if (playlist.current == null){
				playlist.current = playlist.head;
				trackNumber = 0;
			    }
			}
		    }
		else {
		    playlist.current = playlist.current.getNext();
		    trackNumber++;
		    if (playlist.current == null) {
			playlist.current = playlist.head;
			trackNumber = 0;
		    }
		}
		shuffle.remove(trackNumber);
		backgroundPlayer = new MP3Player(playlist.current);
		numPlayed++;
	    }
	    ipsmp.threadIsPlaying = false;
	    chosenFile = null;
	   
	}
    }

}